package com.texaco.chapasFutbol.entidades;

import org.andengine.R;
import org.andengine.engine.Engine.EngineLock;
import org.andengine.entity.IEntity;
import org.andengine.entity.scene.ITouchArea;
import org.andengine.entity.sprite.AnimatedSprite;
import org.andengine.entity.sprite.Sprite;
import org.andengine.input.touch.TouchEvent;
import org.andengine.util.color.Color;
import org.andengine.util.debug.Debug;

import android.util.FloatMath;

import com.texaco.chapasFutbol.resources.Resources;
import com.texaco.chapasFutbol.scene.GameScene;
import com.texaco.chapasFutbol.utilidades.Colores;

/**
 * Clase que maneja el tirador de la chapa.
 * 
 * @author texaco
 * 
 */
public class TiradorChapa implements ITouchArea{

	// Posición X del botón OK del tirador en la hoja de sprites.
	public static final int SHAPE_TIRADOR_OK_X = 0;

	// Posición Y del botón OK del tirador en la hoja de sprites.
	public static final int SHAPE_TIRADOR_OK_Y = 0;

	// Ancho del botón OK del tirador.
	public static final int TIRADOR_OK_WIDTH = 56;

	// Alto del botón OK del tirador.
	public static final int TIRADOR_OK_HEIGHT = 71;

	// Posición X del botón CANCEL del tirador en la hoja de sprites.
	public static final int SHAPE_TIRADOR_CANCEL_X = 74;

	// Posición Y del botón CANCEL del tirador en la hoja de sprites.
	public static final int SHAPE_TIRADOR_CANCEL_Y = 11;

	// Ancho del botón CANCEL del tirador.
	public static final int TIRADOR_CANCEL_WIDTH = 131 - 74;

	// Alto del botón CANCEL del tirador.
	public static final int TIRADOR_CANCEL_HEIGHT = 76 - 11;

	// Posición X del PULSADOR ROJO del tirador en la hoja de sprites.
	public static final int SHAPE_TIRADOR_PULSADOR_ROJO_X = 147;

	// Posición Y del PULSADOR ROJO del tirador en la hoja de sprites.
	public static final int SHAPE_TIRADOR_PULSADOR_ROJO_Y = 0;

	// Ancho del PULSADOR ROJO del tirador.
	public static final int TIRADOR_PULSADOR_ROJO_WIDTH = 255 - 147;

	// Alto del PULSADOR ROJO del tirador.
	public static final int TIRADOR_PULSADOR_ROJO_HEIGHT = 112;

	// Posición X del PULSADOR AZUL del tirador en la hoja de sprites.
	public static final int SHAPE_TIRADOR_PULSADOR_AZUL_X = 273;

	// Posición Y del PULSADOR AZUL del tirador en la hoja de sprites.
	public static final int SHAPE_TIRADOR_PULSADOR_AZUL_Y = 0;

	// Ancho del PULSADOR AZUL del tirador.
	public static final int TIRADOR_PULSADOR_AZUL_WIDTH = 381 - 273;

	// Alto del PULSADOR AZUL del tirador.
	public static final int TIRADOR_PULSADOR_AZUL_HEIGHT = 112;

	// Shape del botón OK del tirador.
	public static final String SHAPE_TIRADOR_OK = "SHAPE_TIRADOR_OK";

	// Shape del botón CANCEL del tirador.
	public static final String SHAPE_TIRADOR_CANCEL = "SHAPE_TIRADOR_CANCEL";

	// Shape del PULSADOR ROJO del tirador.
	public static final String SHAPE_TIRADOR_PULSADOR_ROJO = "SHAPE_TIRADOR_PULSADOR_ROJO";

	// Shape del PULSADOR AZUL del tirador.
	public static final String SHAPE_TIRADOR_PULSADOR_AZUL = "SHAPE_TIRADOR_PULSADOR_AZUL";

	/*
	 * De estado desactivo se puede transitar a:
	 * ESTADO_TIRADOR.
	 */
	public static final String ESTADO_DESACTIVO = "ESTADO_DESACTIVO";
	
	/*
	 * Estado que representa que se está pusando y arrastrando el tirador.
	 * De este estado se puede transitar a:
	 * ESTADO_DECISION
	 */
	public static final String ESTADO_TIRADOR = "ESTADO_TIRADOR";

	/**
	 * ESTADO_TIRADOR_ACTIVO.
	 * Se trata de un sub estado de estado tirador.
	 */
	protected static final String ESTADO_TIRADOR_ACTIVO = "ESTADO_TIRADOR_ACTIVO";
	
	/*
	 * Estado que indica que se puede aceptar, cancelar o modificar le disparo
	 * De este estado se puede transitar a:
	 * ESTADO_TIRADOR (se mueve de nuevo el tirador)
	 * ESTADO_DESASCTIVO (Se dispara o se cancela)
	 */
	public static final String ESTADO_DECISION = "ESTADO_DECISION";
	private String estado = ESTADO_DESACTIVO;
	
	/*
	 * Definimos la separación de los botones con respecto al tirador. Esto
	 * terminará cambiando. Ya que habría que detectar el angulo y colocarlos
	 * con relacción a dicho ángulo.
	 */
	private static final float ALFA_X = 25;
	private static final float ALFA_Y = 25;

//	public static final int VECTOR_FUERZA_WIDTH = 64;
//	public static final int VECTOR_FUERZA_HEIGHT = 64;
	public static final int VECTOR_FUERZA_WIDTH = 664;
	public static final int VECTOR_FUERZA_HEIGHT = 49;

	private static final float PROPORCION_FUERZA_MAXIMA = 350;
//	private static final float DESPLAZAMIENTO_FUERZA_MAXIMA = 30;

	
	private Game game;

	private Sprite tirador;
//	private Circle circulo;
	private Sprite circulo;
	private Sprite bOk;
	private Sprite bCancel;
//	private Sprite vectorFuerza;
	private AnimatedSprite vectorFuerza;

	/*
	 * Origen de la chapa.
	 */
	private float oX;
	private float oY;

	public TiradorChapa(Game game) {
		this.game = game;

		/*
		 * Creamos los sprites.
		 */
//		vectorFuerza = new Sprite(
//			this.oX, 
//			this.oY, 
//			game.getActivity().getVectorMap().get(Resources.VECTOR_FLECHA).getWidth(), 
//			game.getActivity().getVectorMap().get(Resources.VECTOR_FLECHA).getHeight(), 
//			game.getActivity().getVectorMap().get(Resources.VECTOR_FLECHA), 
//			game.getActivity().getVertexBufferObjectManager());
		vectorFuerza = new AnimatedSprite(this.oX, this.oY, game.getActivity().mVectorTextureRegion, game.getActivity().getVertexBufferObjectManager());
		
		tirador = new Sprite(0, 0, game.getActivity().getShapesMaps()
				.get(Resources.SHAPE_TIRADOR), game.getActivity()
				.getVertexBufferObjectManager()) {
			@Override
			public boolean onAreaTouched(TouchEvent pSceneTouchEvent,
					float pTouchAreaLocalX, float pTouchAreaLocalY) {
				estado = ESTADO_TIRADOR_ACTIVO;
				if(pSceneTouchEvent.isActionOutside()){
					Debug.d("accion outside");
				}else if(pSceneTouchEvent.isActionCancel()){
					Debug.d("accion cancel");
				}else if(pSceneTouchEvent.isActionDown()){
					ocultarBotones();
				}else if(pSceneTouchEvent.isActionUp()){
//					ocultarBotones();
					TiradorChapa.this.game.mostrarBotonesTirador();
					estado = ESTADO_TIRADOR;
				}else if(pSceneTouchEvent.isActionMove()){
					TiradorChapa.this.getTirador(pSceneTouchEvent.getX(), pSceneTouchEvent.getY());
					TiradorChapa.this.getVectorFuerza(pSceneTouchEvent.getX(), pSceneTouchEvent.getY());
				} 
				return true;
			}
		};
		
		bOk = new Sprite(ALFA_X, game.getActivity().getEngine().getCamera().getHeight() - ALFA_Y - 
				Resources.graphicResources.get(Resources.ATLAS_BOTONES).getResources().get(Resources.SHAPE_CHUT_OK).getHeight(),
				game.getActivity().getShapesMaps().get(Resources.SHAPE_CHUT_OK), game
						.getActivity().getVertexBufferObjectManager()) {
			public boolean onAreaTouched(TouchEvent pSceneTouchEvent,
					float pTouchAreaLocalX, float pTouchAreaLocalY) {
				if(pSceneTouchEvent.isActionUp()){
					TiradorChapa.this.aceptarDisparo();
					return true;
				}
				return false;
			};
		};
		bOk.setScale(0.8f);

		bCancel = new Sprite(game.getActivity().getEngine().getCamera().getWidth() - ALFA_X - 
				Resources.graphicResources.get(Resources.ATLAS_BOTONES).getResources().get(Resources.SHAPE_CHUT_CANCEL).getWidth(),
				game.getActivity().getEngine().getCamera().getHeight() - ALFA_Y - 
				Resources.graphicResources.get(Resources.ATLAS_BOTONES).getResources().get(Resources.SHAPE_CHUT_CANCEL).getHeight(), 
				game.getActivity()
						.getShapesMaps().get(Resources.SHAPE_CHUT_CANCEL), game
						.getActivity().getVertexBufferObjectManager()) {
			public boolean onAreaTouched(TouchEvent pSceneTouchEvent,
					float pTouchAreaLocalX, float pTouchAreaLocalY) {
				if(pSceneTouchEvent.isActionUp()){
					TiradorChapa.this.cancelaDisparo();
					return true;
				}
				return false;
			};
		};
		bCancel.setScale(0.8f);

		
//		circulo = new Circle(0, 0, 1, 50, game.getActivity().getVertexBufferObjectManager());
		circulo = new Sprite(this.oX, this.oY, Resources.vectors.get(
				Resources.VECTOR_CIRCULO).getWidth(), Resources.vectors.get(
				Resources.VECTOR_CIRCULO).getHeight(), game.getActivity()
				.getVectorMap().get(Resources.VECTOR_CIRCULO), game
				.getActivity().getVertexBufferObjectManager());

	}

	protected void cancelaDisparo() {
		game.eliminaHalos();
		estado = ESTADO_DESACTIVO;
		ocultarTirador();
		game.cancelaChapaPulsada();
		
		// Ocultamos el vector fuerza.
		ocultaVectorFuerza();
		
		// Volvemoa a mostrar los halos de posición.
		game.colocaHalos();
	}

	/**
	 * Este método informa de que se ha aceptado el disparo según la posición
	 * del tirador. Elimina los botones y el tirador. Informa al Juego del
	 * disparo.
	 */
	protected void aceptarDisparo() {
		estado = ESTADO_DESACTIVO;
		game.aceptarDisparo(getDiferenciaX(), getDiferenciaY());
		ocultarTirador();
	}

	private float getDiferenciaX() {
		return oX - getCenterX();
	}

	private float getDiferenciaY() {
		return oY - getCenterY();
	}

	private float getCenterY() {
		return tirador.getY() + tirador.getHeight()/2;
	}
	
	private float getCenterX() {
		return tirador.getX() + tirador.getWidth()/2;
	}
	
	public void ocultarTirador() {
		TiradorChapa.this.game.clearHudTouchAreas();
		TiradorChapa.this.game.clearGameTouchAreas();
		final EngineLock engineLock = game.getActivity().getEngine()
				.getEngineLock();
		engineLock.lock();
		IEntity layerPadre = tirador.getParent();
		if (layerPadre != null) {
			layerPadre.detachChildren();
		}
		layerPadre = bOk.getParent();
		if (layerPadre != null) {
			layerPadre.detachChildren();
			//CON ESTO ELIMINAMOS TANTO EL CANCEL COMO EL OK.
		}
		
		/*
		 * Quitamos el circulos.
		 */
//		layerPadre = circulo.getEntity().getParent();
		layerPadre = circulo.getParent();
		if (layerPadre != null) {
			layerPadre.detachChildren();
		}
		engineLock.unlock();
	}

	protected void ocultarBotones() {
		game.clearHudTouchAreas();
		final EngineLock engineLock = game.getActivity().getEngine()
				.getEngineLock();
		engineLock.lock();
		IEntity layerPadre = bOk.getParent();
		if (layerPadre != null) {
			layerPadre.detachChildren();
			//CON ESTO ELIMINAMOS TANTO EL CANCEL COMO EL OK.
		}
		engineLock.unlock();
	}
	
	public Sprite getTirador(float x, float y, Sprite chapa) {
		estado = ESTADO_TIRADOR;
		this.oX = chapa.getX() + Chapa.WIDTH / 2;
		this.oY = chapa.getY() + Chapa.HEIGHT / 2;
//		this.game.mostrarBotonesTirador();
//		this.game.eliminarAreaListeners();
		return getTirador(x, y);
	}

	public AnimatedSprite getVectorFuerza(float x, float y, Sprite chapa) {
		this.oX = chapa.getX() + Chapa.WIDTH / 2;
		this.oY = chapa.getY() + Chapa.HEIGHT / 2;
		return getVectorFuerza(x, y);
	}
	
	/*
	 * Tenemos que controlar la fuerza máxima con la
	 * que se mueve el tirador.
	 */
	public Sprite getTirador(float x, float y) {
		/*
		 * Comprobar si la magnitud es superior a lo establecido.
		 */
		float vectorX = x - oX;
		float vectorY = y - oY;
		
//		double mag = Math.sqrt((vectorX*vectorX) + (vectorY*vectorY));
		double mag = FloatMath.sqrt((vectorX*vectorX) + (vectorY*vectorY));
		
		if(mag > game.getActivity().getResources().getInteger(R.integer.magnitud_maxima)){
//			if(mag > 2){
			/*
			 * Tenemos que normalizar para tener el tirador en elmismo ángulo pero con la
			 * magnitud máxima.
			 */
			double angulo = Math.atan(vectorY/vectorX);
			if(vectorX < 0){
				angulo += Math.PI;
			}
				
			vectorX = (float) (game.getActivity().getResources().getInteger(R.integer.magnitud_maxima) * Math.cos(angulo));
			vectorY = (float) (game.getActivity().getResources().getInteger(R.integer.magnitud_maxima) * Math.sin(angulo));
			
			x = oX + vectorX;
			y = oY + vectorY;
			mag = game.getActivity().getResources().getInteger(R.integer.magnitud_maxima);
		}
		
		tirador.setPosition(x - tirador.getWidth() / 2, y - tirador.getHeight() / 2);
//		circulo.change(oX, oY, (float) mag);
		circulo.setPosition(oX - (float)Math.abs(mag), oY - (float)Math.abs(mag));
		circulo.setHeight((float) (mag*2));
		circulo.setWidth((float) (mag*2));

		return tirador;
	}

	public Sprite getTirador() {
		return tirador;
	}

	public Sprite getBotonOk() {
		return bOk;
	}

	public Sprite getBotonCancel() {
		return bCancel;
	}

	public boolean isEstadoDesactivo(){
		return estado.equals(ESTADO_DESACTIVO);
	}
	
	public boolean isEstadoTirador(){
		return estado.equals(ESTADO_TIRADOR) || estado.equals(ESTADO_TIRADOR_ACTIVO);
	}
	
	public boolean isEstadoDecision(){
		return estado.equals(ESTADO_DECISION);
	}
	
	/**
	 * Indica si está en el evento del tirador.
	 * @return
	 */
	public boolean isEventoTirador(){
		return estado.equals(ESTADO_TIRADOR_ACTIVO);
	}
	
	/**
	 * Resetea el estado del evento del tirador.
	 * Esto se da cuando se suelta la pantalla estando fuera del tirador.
	 */
	public void resetEventoTirador(){
		if(isEventoTirador()){
			estado = ESTADO_TIRADOR;
		}
	}
	
	/**
	 * Método que muestra por pantalla un vector indicando la direcicón y la
	 * fuerza con la que se lanzara la chapa al soltar.
	 * 
	 * TODO: ESTO HAY QUE UNIFICARLO CON EL TIRADOR.
	 * 
	 * @param pSceneTouchEvent
	 */
	public AnimatedSprite getVectorFuerza(float x, float y) {
		
		/*
		 * Calculamos la diferencia
		 */
		float diffX = oX - x;
		float diffY = oY - y;
		
//		double proporcionFuerza = Math.sqrt((diffX*diffX) + (diffY*diffY));
		double proporcionFuerza = FloatMath.sqrt((diffX*diffX) + (diffY*diffY));
		if (proporcionFuerza > PROPORCION_FUERZA_MAXIMA){
			proporcionFuerza = PROPORCION_FUERZA_MAXIMA;
		}
		
		float a = oX-(VECTOR_FUERZA_WIDTH/2);
		float b = oY-(VECTOR_FUERZA_HEIGHT/2);
		 
		// Establecemos un límite posicional para le flecha.
//		double ang = Math.atan(diffY/diffX);
//		if(diffX < 0){
//			ang += Math.PI;
//		}
//			
//		diffX = (float) (DESPLAZAMIENTO_FUERZA_MAXIMA * Math.cos(ang));
//		diffY = (float) (DESPLAZAMIENTO_FUERZA_MAXIMA * Math.sin(ang));
		
		a = a + diffX;
		b = b + diffY;
		
		double radio = Math.atan2(-diffY, -diffX);
        double angulo = Math.toDegrees(radio);
        vectorFuerza.setRotationCenter(5, 5);
        vectorFuerza.setRotation((float)(180+angulo));
		
//		vectorFuerza.setWidth(VECTOR_FUERZA_WIDTH + (float)proporcionFuerza);
//		vectorFuerza.setHeight(VECTOR_FUERZA_HEIGHT + (float)proporcionFuerza);
//      vectorFuerza.setPosition(a,b);
		vectorFuerza.setPosition(oX, oY);
		vectorFuerza.animate(200);
		
        // Este valor dependerá de si la flecha está vertical o no.
        // FIXME: no hardcodear este valor
        
        // Array de colores, de verde a rojo.
//        String[] colores = {
//        		"#7ACC00", "#8FCC00", "#A3CC00", "#B8CC00", "#CCCC00", 
//        		"#CCB800", "#CCA300", "#CC8F00", "#CC7A00", "#CC6600", 
//        		"#CC5200", "#CC3D00", "#CC2900", "#CC1400", "#CC0000"};
//        
//        int i = 0;
//        
//        if (proporcionFuerza > 0 && proporcionFuerza < 20){
//        	i = 0;
//        }else if (proporcionFuerza >= 20 && proporcionFuerza < 40){
//        	i = 1;
//        }else if (proporcionFuerza >= 40 && proporcionFuerza < 60){
//        	i = 2;
//        }else if (proporcionFuerza >= 60 && proporcionFuerza < 80){
//        	i = 3;
//        }else if (proporcionFuerza >= 80 && proporcionFuerza < 100){
//        	i = 4;
//        }else if (proporcionFuerza >= 100 && proporcionFuerza < 120){
//        	i = 5;
//        }else if (proporcionFuerza >= 120 && proporcionFuerza < 140){
//        	i = 6;
//        }else if (proporcionFuerza >= 140 && proporcionFuerza < 160){
//        	i = 7;
//        }else if (proporcionFuerza >= 160 && proporcionFuerza < 180){
//        	i = 8;
//        }else if (proporcionFuerza >= 180 && proporcionFuerza < 200){
//        	i = 9;
//        }else if (proporcionFuerza >= 200 && proporcionFuerza < 220){
//        	i = 10;
//        }else if (proporcionFuerza >= 220 && proporcionFuerza < 240){
//        	i = 11;
//        }else if (proporcionFuerza >= 240 && proporcionFuerza < 260){
//        	i = 12;
//        }else if (proporcionFuerza >= 260 && proporcionFuerza < 280){
//        	i = 13;
//        }else if (proporcionFuerza >= 280){
//        	i = 14;
//        } 
//        
//		double [] arrayColors = Colores.hexToOpenGL(colores[i]);
//		vectorFuerza.setColor(
//				(float)arrayColors[0], 
//				(float)arrayColors[1], 
//				(float)arrayColors[2]);
////            vectorFuerza.setAlpha(0.7f);
        
		return vectorFuerza;
		
	}
	
	/**
	 * Método que oculta de la pantalla el vector fuerza.
	 */
	public void ocultaVectorFuerza(){
		final EngineLock engineLock = game.getActivity().getEngine().getEngineLock();
		engineLock.lock();
		game.getSceneHandler().getGame().getChildByIndex(GameScene.LAYER_VECTOR_FUERZA).detachChild(vectorFuerza);
		engineLock.unlock();
	}

	public IEntity getCirculo() {
		return circulo;
//		return circulo.getEntity();
	}

	/**
	 * Se queda intencionadamente vacío
	 */
	public boolean contains(float pX, float pY) {
		// TODO Auto-generated method stub
		return false;
	}

	/**
	 * Se queda intencionadamente vacío
	 */
	public float[] convertSceneToLocalCoordinates(float pX, float pY) {
		// TODO Auto-generated method stub
		return null;
	}

	/**
	 * Se queda intencionadamente vacío
	 */
	public float[] convertLocalToSceneCoordinates(float pX, float pY) {
		// TODO Auto-generated method stub
		return null;
	}

	/**
	 * Implementamos onAreaTouched de forma que cuando se dispare el evento lo 
	 * pasamos al tirador para que lo gesitone.
	 */
	public boolean onAreaTouched(TouchEvent pSceneTouchEvent,
			float pTouchAreaLocalX, float pTouchAreaLocalY) {
		return tirador.onAreaTouched(pSceneTouchEvent, pTouchAreaLocalX, pTouchAreaLocalY);
	}
}
